package com.xh.util;

import com.xh.model.AdDepartment;
import com.xh.model.User;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.*;

public class ADUtils {
    private static final Log log = LogFactory.getLog(ADUtils.class);

    // 连接ad域
    public static LdapContext getContext(Hashtable<String, String> hashtable) throws NamingException {
        LdapContext ctx = new InitialLdapContext(hashtable, null);
        return ctx;
    }

    public static NamingEnumeration<SearchResult> getSearchResultUser(LdapContext ctx, String searchFilter, String searchBase) throws NamingException {
        // 搜索控制器
        SearchControls searchCtls = new SearchControls();
        // 创建搜索控制器
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String returnedAtts[] = {"objectGUID", "sn", "givenName", "displayName", "initials", "userPrincipalName", "telephoneNumber", "title", "mobile", "mail", "whenCreated", "sAMAccountName", "distinguishedName", "name", "departmentNumber", "homePhone", "department", "whenChanged"}; // 定制返回属性

        searchCtls.setReturningAttributes(returnedAtts);
        NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);
        return answer;
    }

    public static NamingEnumeration<SearchResult> getSearchResult(LdapContext ctx, String searchFilter, String searchBase) throws NamingException {
        // 搜索控制器
        SearchControls searchCtls = new SearchControls();
        // 创建搜索控制器
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String returnedAtts[] = {"objectGUID", "canonicalName", "distinguishedName", "id", "name", "userPrincipalName", "departmentNumber", "telephoneNumber", "homePhone", "mobile", "department", "sAMAccountName", "whenChanged"}; // 定制返回属性
        searchCtls.setReturningAttributes(returnedAtts);
        NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);
        return answer;
    }

    public static List<User> getUsers(LdapContext ctx, String searchBase) throws NamingException {
        // LDAP搜索过滤器类，此处只获取AD域用户，所以条件为用户user或者person均可
        String searchFilter = ADProperty.get("Ldap.searchFilterUser");

        NamingEnumeration<SearchResult> answer = getSearchResultUser(ctx, searchFilter, searchBase);

        List<User> users = new ArrayList<User>();
        while (answer.hasMoreElements()) {
            SearchResult sr = answer.next();
            User u = new User();
            u.setObjectGUID(getGUID(getAttrValue(sr, "objectGUID").toString().getBytes()));
            u.setUserName(getAttrValue(sr, "sAMAccountName"));
            u.setcName(getAttrValue(sr, "displayName"));
            u.setMobile(getAttrValue(sr, "mobile"));
            u.setEmail(getAttrValue(sr, "mail"));
            u.setDistinguishedName(getAttrValue(sr, "distinguishedName"));
            log.debug(u.toString());
            users.add(u);

        }
        return users;
    }

    // 获取部门列表
    public static TreeSet<AdDepartment> getAdDepartment(LdapContext ctx, String searchBase) throws NamingException {
        // LDAP搜索过滤器类，此处只获取AD域用户，所以条件为用户user或者person均可
        String searchFilter = ADProperty.get("Ldap.searchFilterRole");

        NamingEnumeration<SearchResult> answer = getSearchResult(ctx, searchFilter, searchBase);

        TreeSet<AdDepartment> treeSet = new TreeSet<AdDepartment>();
        while (answer.hasMoreElements()) {
            SearchResult sr = answer.next();
            AdDepartment adDepartment = new AdDepartment();
            adDepartment.setObjectGUID(getGUID(getAttrValue(sr, "objectGUID").toString().getBytes()));
            adDepartment.setName(getAttrValue(sr, "name"));
            adDepartment.setcName(getAttrValue(sr, "canonicalName"));
            adDepartment.setDistinguishedName(getAttrValue(sr, "distinguishedName"));
            log.debug(adDepartment.toString());
            treeSet.add(adDepartment);
        }
        return treeSet;
    }

    public static AdDepartment getTreeAdDepartment(TreeSet<AdDepartment> treeSet, String searchBase) {
        AdDepartment root = new AdDepartment();
        root.setName(searchBase);
        root.setcName(searchBase);
        for (AdDepartment ad : treeSet) {
            AdDepartment parentAdDepartment = null;
            if ((parentAdDepartment = root.getParentAdDepartmentBycName(ad.getcName())) != null) {
                parentAdDepartment.addChildren(ad);
            } else {
                root.addChildren(ad);
            }
        }
        return root;
    }

    private static String getAttrValue(SearchResult sr, String attr) throws NamingException {
        Attributes Attrs = sr.getAttributes();
        if (Attrs.get(attr) == null) {
            return null;
        }
        return Attrs.get(attr).getAll().next().toString();
    }

    private static String getGUID(byte[] inArr) {
        StringBuffer guid = new StringBuffer();
        for (int i = 0; i < inArr.length; i++) {
            StringBuffer dblByte = new StringBuffer(Integer.toHexString(inArr[i] & 0xff));
            if (dblByte.length() == 1) {
                guid.append("0");
            }
            guid.append(dblByte);
        }
        return guid.toString();
    }

}